﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace House.Server.Repository
{
    using ServiceStack.OrmLite;
    using System.Data;
    using System.Linq.Expressions;

    /// <summary>
    /// 基于泛型的基类
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    public class GenericBaseRepository<T> : Factory where T : class
    {
        /// <summary>
        /// 数据库连接
        /// </summary>
        public IDbConnection DbConnection
        {
            get
            {
                return base.DbFactory.OpenDbConnection();
            }
        }


        #region 通用查询

        /// <summary>
        /// 插入数据（通用方法）
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="obj">实例</param>
        /// <returns></returns>
        public bool Insert(T obj)
        {
            using (var cnn = DbConnection)
            {
                var result = cnn.Insert<T>(obj);
                return result > 0;
            }
        }

        /// <summary>
        /// 插入数据（通用方法）
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="obj">实例</param>
        /// <param name="index">最后插入ID</param>
        /// <returns></returns>
        public bool Insert(T obj, out long index)
        {
            using (var cnn = DbConnection)
            {
                var id = cnn.Insert<T>(obj, selectIdentity: true);
                index = id;
                return id > 0;
            }
        }

        /// <summary>
        /// 批量插入
        /// </summary>
        /// <param name="dtos">批量对象</param>
        /// <returns></returns>
        public bool InsertAll(IEnumerable<T> dtos)
        {
            using (var cnn = DbConnection)
            {
                cnn.InsertAll<T>(dtos);
                return true;
            }
        }

        /// <summary>
        /// 修改数据（通用方法）
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="obj">实例</param>
        /// <returns></returns>
        public bool Update(T obj)
        {
            using (var cnn = DbConnection)
            {
                var result = cnn.Update<T>(obj);
                return result > 0;
            }
        }
        /// <summary>
        /// 修改数据（通用方法）
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="obj">实例</param>
        /// <param name="Where">Labmda条件</param>
        /// <returns></returns>
        public bool Update(T obj, Expression<Func<T, bool>> Where)
        {
            using (var cnn = DbConnection)
            {
                var result = cnn.Update<T>(obj, Where);
                return result > 0;
            }
        }
        /// <summary>
        /// 修改数据（通用方法）
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="obj">实例</param>
        /// <param name="onlyFields">Labmda指定字段</param>
        /// <returns></returns>
        public bool UpdateOnly(T obj, Expression<Func<T, object>> onlyFields)
        {
            using (var cnn = DbConnection)
            {
                var result = cnn.UpdateOnly(obj, onlyFields);
                return result > 0;
            }
        }

        /// <summary>
        /// 修改数据（通用方法）
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="obj">实例</param>
        /// <param name="onlyFields">Labmda指定字段</param>
        ///<param name="Where">Labmda条件</param>
        /// <returns></returns>
        public bool UpdateOnly(T obj, Expression<Func<T, object>> onlyFields, Expression<Func<T, bool>> Where)
        {
            using (var cnn = DbConnection)
            {
                var result = cnn.UpdateOnly(obj, onlyFields, Where);
                return result > 0;
            }
        }

        /// <summary>
        ///查询（通用方法）
        /// </summary>
        /// <returns></returns>
        public List<T> Select()
        {
            using (var cnn = DbConnection)
            {
                return cnn.Select<T>();
            }
        }
        /// <summary>
        ///查询（通用方法）
        /// </summary>
        /// <param name="predicate">Labmda条件</param>
        /// <returns></returns>
        public List<T> Select(Expression<Func<T, bool>> predicate)
        {
            using (var cnn = DbConnection)
            {
                return cnn.Select<T>(predicate);
            }
        }

        /// <summary>
        /// 通用分页查询
        /// </summary>
        /// <param name="pageIndex">页序号（从1开始）</param>
        /// <param name="pageSize">每页条数</param>
        /// <returns></returns>
        public List<T> SelectByPager(int pageIndex, int pageSize, out long totalSize)
        {
            return SelectByPager(null, pageIndex, pageSize, out totalSize);
        }

        /// <summary>
        /// 通用分页查询
        /// </summary>
        /// <param name="Where">条件</param>
        /// <param name="pageIndex">页序号（从1开始）</param>
        /// <param name="pageSize">每页条数</param>
        /// <returns></returns>
        public List<T> SelectByPager(Expression<Func<T, bool>> Where, int pageIndex, int pageSize, out long totalSize)
        {
            using (var conn = DbConnection)
            {
                var ev = OrmLiteConfig.DialectProvider.SqlExpression<T>();
                if (Where != null)
                    ev.Where<T>(Where);
                ev.Limit((pageIndex - 1) * pageSize, pageSize);
                if (Where != null)
                    totalSize = conn.Count<T>(Where);
                else
                    totalSize = conn.Count<T>();
                return conn.Select<T>(ev);
            }
        }

        /// <summary>
        /// 通用分页查询
        /// </summary>
        /// <param name="pageIndex">页序号（从1开始）</param>
        /// <param name="pageSize">每页条数</param>
        /// <returns></returns>
        public List<T> SelectByPagerDesc(Expression<Func<T, object>> Desc, int pageIndex, int pageSize, out long totalSize)
        {
            return SelectByPagerDesc(null, Desc, pageIndex, pageSize, out totalSize);
        }

        /// <summary>
        /// 通用分页查询
        /// </summary>
        /// <param name="Where">条件</param>
        /// <param name="pageIndex">页序号（从1开始）</param>
        /// <param name="pageSize">每页条数</param>
        /// <returns></returns>
        public List<T> SelectByPagerDesc(Expression<Func<T, bool>> Where, Expression<Func<T, object>> Desc, int pageIndex, int pageSize, out long totalSize)
        {
            using (var conn = DbConnection)
            {
                var ev = OrmLiteConfig.DialectProvider.SqlExpression<T>();
                ev.OrderByDescending(Desc);
                if (Where != null)
                    ev.Where<T>(Where);
                ev.Limit((pageIndex - 1) * pageSize, pageSize);
                if (Where != null)
                    totalSize = conn.Count<T>(Where);
                else
                    totalSize = conn.Count<T>();
                return conn.Select<T>(ev);
            }
        }


        public List<T> SelectByPagerDesc(string xx, Expression<Func<T, bool>> Where, Expression<Func<T, object>> Desc, int pageIndex, int pageSize, out long totalSize)
        {
            using (var conn = DbConnection)
            {
                var ev = OrmLiteConfig.DialectProvider.SqlExpression<T>();
                ev.OrderByDescending(Desc);
                if (Where != null)
                    ev.Where<T>(Where);
                ev.Limit((pageIndex - 1) * pageSize, pageSize);
                if (Where != null)
                    totalSize = conn.Count<T>(Where);
                else
                    totalSize = conn.Count<T>();
                return conn.Select<T>(ev);
            }
        }

        /// <summary>
        /// 查询多条数据 类似in
        /// </summary>
        /// <param name="ids">主键集合</param>
        /// <returns></returns>
        public List<T> SelectByIds(System.Collections.IEnumerable ids)
        {
            using (var cnn = DbConnection)
            {
                return cnn.SelectByIds<T>(ids);
            }
        }

        /// <summary>
        /// 查询单条数据 通过主键查询
        /// </summary>
        /// <param name="ids">主键集合</param>
        /// <returns></returns>
        public T SelectById(int id)
        {
            using (var cnn = DbConnection)
            {
                var rtv = cnn.SingleById<T>(id);
                return rtv;
            }
        }

        /// <summary>
        /// 删除数据（通用方法）
        /// </summary>
        /// <param name="id">主键删除</param>
        /// <returns></returns>
        public bool DeleteById(int id)
        {
            using (var cnn = DbConnection)
            {
                var result = cnn.DeleteById<T>(id);
                return result > 0;
            }
        }

        /// <summary>
        /// 删除数据（通用方法）
        /// </summary>
        /// <param name="id">主键删除</param>
        /// <param name="Where">Labmda条件</param>
        /// <returns></returns>
        public bool Delete(Expression<Func<T, bool>> Where)
        {
            using (var cnn = DbConnection)
            {
                var result = cnn.Delete<T>(Where);
                return result > 0;
            }
        }

        #endregion
    }
}
